package com.luming.tkbatis.common.base;

import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import com.github.pagehelper.PageHelper;
import com.luming.tkbatis.annotation.BizCodeLevel;
import com.luming.tkbatis.common.BaseDbPo;
import com.luming.tkbatis.common.BaseMapper;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.additional.aggregation.AggregateCondition;
import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Builder;
import tk.mybatis.mapper.mapperhelper.EntityHelper;
import tk.mybatis.mapper.util.Sqls;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author sunsulei
 */
//public abstract class BaseService<T extends BaseDbPo> {
//
//    private static final String PERCENT = "%";
//    private static final String UNDER_LINE = StrUtil.UNDERLINE;
//    private static final String BACKSLASH = StrUtil.BACKSLASH;
//    protected final Log log = Log.get(getClass());
//    @Autowired
//    private BaseMapper<T> baseMapper;
//
//    public T selectOne(T record) {
//        try {
//            //此处的5 没有特殊含义 只是为了数据更加真实
//            PageHelper.startPage(1, 5, false);
//            List<T> select = this.select(record);
//
//            if (CollUtil.isNotEmpty(select) && select.size() > 1) {
//                log.warn("selectOne 查询除了多条数据,部分数据存在问题,请检查.查询实体:{}", JSONUtil.toJsonStr(record));
//            }
//
//            return CollUtil.getFirst(select);
//        } finally {
//            //PageHelper.clearPage();
//        }
//    }
//
//    public List<T> selectByExample(T record) {
//        Sqls sqls = this.buildGenericSqlsWithEquals(record);
//        Example build = this.example().andWhere(sqls).build();
//        return this.selectByExample(build);
//    }
//
//    public List<T> select(T record) {
//        return selectByExample(record);
//    }
//
//    public Builder example() {
//        Builder builder = Example.builder(classByT());
//        String bizCodeForQuery = bizCodeConvert(BizCodeConfig.bizCodeForQuery(), BizCodeLevel.Scope.query);
//
//        if (StrUtil.isBlank(bizCodeForQuery)) {
//            return builder;
//        }
//
//        /*
//         * bizCode 参数的包装.
//         * 1.如果完全隔离,忽略租户层级关系.
//         * 2.层级查询,子看所有父,通过 bizCode in (所有父级 bizCode)
//         *           父看所有子,通过父 bizCode like 'parent_%'.
//         */
//        Sqls sqls;
//
//        if (needQueryWithBizCodeLike()) {
//            sqls = Sqls.custom().andIn("bizCode", listBizCodeConvert(bizCodeForQuery));
//            sqls.orLike("bizCode", StrUtil.format("{}{}", bizCodeForQuery, "\\_%"));
//        } else {
//            sqls = Sqls.custom().andEqualTo("bizCode", bizCodeForQuery);
//        }
//
//        builder.where(sqls);
//        return builder;
//    }
//
//    /**
//     * 判定当期实体是否根据 bizCode 完全隔离,不承认租户间的继承关系.
//     */
//    private boolean needQueryWithBizCodeLike() {
//        BizCodeLevel bizCodeLevel = AnnotationUtil.getAnnotation(classByT(), BizCodeLevel.class);
//        if (bizCodeLevel == null) {
//            return true;
//        }
//
//        BizCodeLevel.Level query = bizCodeLevel.query();
//        return query != BizCodeLevel.Level.tenant;
//    }
//
//    /**
//     * bizCode 转换
//     * Ex. a_b_c_d  -> [a , a_b , a_b_c , a_b_c_d]
//     */
//    private List<String> listBizCodeConvert(String bizCode) {
//        List<String> bizCodeList = CollUtil.newArrayList();
//
//        List<String> split = StrUtil.split(bizCode, StrUtil.UNDERLINE);
//
//        String temp = "";
//
//        for (String s : split) {
//            if (StrUtil.isBlank(temp)) {
//                temp += s;
//            } else {
//                temp = StrUtil.format("{}{}{}", temp, StrUtil.UNDERLINE, s);
//            }
//            bizCodeList.add(temp);
//        }
//
//        return bizCodeList;
//    }
//
//    //包装通用sql.
//    public Sqls buildGenericSqlsWithEquals(T record) {
//        return buildGenericSqlsWithEqualsAndLike(record, Collections.emptyList());
//    }
//
//    public Sqls buildGenericSqlsWithEqualsAndLike(T record, String... propertLike) {
//        List<String> propertLikeList = CollUtil.newArrayList(propertLike);
//        return buildGenericSqlsWithEqualsAndLike(record, propertLikeList);
//    }
//
//    public Sqls buildGenericSqlsWithEqualsAndLike(T record, List<String> propertLikeList) {
//
//        Sqls sqls = Sqls.custom();
//        Set<EntityColumn> allColumns = EntityHelper.getColumns(record.getClass());
//
//        //处理字符串类型的 值等于 数据
//        allColumns.stream()
//                .filter(e -> ReflectUtil.getFieldValue(record, e.getProperty()) != null)
//                .filter(e -> e.getJavaType().equals(String.class))
//                .filter(e -> !CollUtil.contains(propertLikeList, e.getProperty()))
//                .filter(e -> StrUtil.isNotBlank(Convert.toStr(ReflectUtil.getFieldValue(record, e.getProperty()))))
//                .forEach(e -> sqls.andEqualTo(e.getProperty(), ReflectUtil.getFieldValue(record, e.getProperty())));
//
//        //处理字符串类型的 值like 数据
//        allColumns.stream()
//                .filter(e -> ReflectUtil.getFieldValue(record, e.getProperty()) != null)
//                .filter(e -> e.getJavaType().equals(String.class))
//                .filter(e -> CollUtil.contains(propertLikeList, e.getProperty()))
//                .filter(e -> StrUtil.isNotBlank(Convert.toStr(ReflectUtil.getFieldValue(record, e.getProperty()))))
//                .forEach(e -> sqls.andLike(e.getProperty(), buildLikeParam(ReflectUtil.getFieldValue(record, e.getProperty()))));
//
//        //处理布尔类型的数据
//        allColumns.stream()
//                .filter(e -> ReflectUtil.getFieldValue(record, e.getProperty()) != null)
//                .filter(e -> e.getJavaType().equals(Boolean.class))
//                .forEach(e -> sqls.andEqualTo(e.getProperty(), BooleanUtil.isTrue((Boolean) ReflectUtil.getFieldValue(record, e.getProperty()))));
//
//
//        allColumns.stream()
//                .filter(e -> ReflectUtil.getFieldValue(record, e.getProperty()) != null)
//                .filter(e -> !e.getJavaType().equals(String.class))
//                .filter(e -> !e.getJavaType().equals(Boolean.class))
//                .forEach(e -> sqls.andEqualTo(e.getProperty(), ReflectUtil.getFieldValue(record, e.getProperty())));
//
//        if (StrUtil.isNotBlank(record.getBizCode())) {
//            //先删除 bizCode
//            sqls.getCriteria().getCriterions().removeIf(e -> StrUtil.equals(e.getProperty(), "bizCode"));
//            sqls.andEqualTo("bizCode", bizCodeConvert(BizCodeConfig.bizCodeForQuery(record.getBizCode()), BizCodeLevel.Scope.query));
//        }
//
//        return sqls;
//    }
//
//    /**
//     * 注意.不带任何参数.如是否有效,是否删除.默认是忽略的.
//     */
//    public List<T> selectAll() {
//        log.warn("******请注意当前调用是否必要******");
//        return baseMapper.selectAll();
//    }
//
//    /**
//     * 判断是否存在. 相比于查数量,性能高点.
//     */
//    public boolean exist(T record) {
//        PageHelper.startPage(1, 2);
//        List<T> select = this.select(record);
//        return select.size() > 0;
//    }
//
//    /**
//     * 查询数量
//     */
//    public int selectCount(T record) {
//        return (int) PageHelper.count(() -> this.selectByExample(record));
//    }
//
//    /**
//     * 根据主键id查询数据.
//     *
//     * @param key:主键id
//     */
//    public T selectByPrimaryKey(Long key) {
//        return selectByPrimaryKeyAndEnable(key, true);
//    }
//
//    /**
//     * 根据主键id和是否启用查询数据(可为null).
//     */
//    public T selectByPrimaryKeyAndEnable(Long key, Boolean enable) {
//        assertPrimaryKeyNotNull(key);
//
//        T instance = instance();
//        instance.setId(key);
//
//        if (ReflectUtil.hasField(instance.getClass(), "enable")) {
//            ReflectUtil.setFieldValue(instance, "enable", enable);
//        }
//
//        return selectOne(instance);
//    }
//
//    public int insertSelective(T record) {
//        setCreatorAndTimeIfNeeded(record);
//        setWriteBizCode(record);
//        record.setId(null);
//        return baseMapper.insertSelective(record);
//    }
//
//    public int updateByPrimaryKeySelective(T record) {
//        assertPrimaryKeyNotNull(record);
//        setModifierAndTimeIfNeeded(record);
//        return baseMapper.updateByPrimaryKeySelective(record);
//    }
//
////    public int updateByPrimaryKey(T record) {
////        assertPrimaryKeyNotNull(record);
////        setModifierAndTimeIfNeeded(record);
////        return baseMapper.updateByPrimaryKey(record);
////    }
//
//    public List<T> selectByExample(Example example) {
//        try {
//            return baseMapper.selectByExample(example);
//        } catch (Exception e) {
//            log.error(e, "example查询出现错误,example:{}", example);
//            handleSqlException(e);
//        }
//        return Collections.emptyList();
//    }
//
//    public int updateByExampleSelective(T record, Example example) {
//        setModifierAndTimeIfNeeded(record);
//        return baseMapper.updateByExampleSelective(record, example);
//    }
//
//    /**
//     * 根据实体id进行更新并标记删除状态。
//     *
//     * @param recordKey:主键id
//     */
//    public boolean deleteById(Long recordKey) {
//        assertPrimaryKeyNotNull(recordKey);
//        return deleteByIdList(Collections.singletonList(recordKey)) == 1;
//    }
//
//    /**
//     * 根据 id 集合更新所有数据.
//     */
//    public int updateByIdList(List<Long> idList, T record) {
//        if (CollUtil.isEmpty(idList) || CollUtil.hasNull(idList)) {
//            return 0;
//        }
//
//        Sqls sqls = Sqls.custom().andIn("id", idList);
//        Builder example = this.example().where(sqls);
//        return this.updateByExampleSelective(record, example.build());
//    }
//
//    /**
//     * 根据主键 id 集合查询数据.
//     */
//    public List<T> selectByIdList(List<Long> idList) {
//        if (CollUtil.isEmpty(idList) || CollUtil.hasNull(idList)) {
//            return Collections.emptyList();
//        }
//
//        Sqls sqls = Sqls.custom().andIn("id", idList);
//
//        Builder example = this.example();
//        example.andWhere(sqls);
//        return baseMapper.selectByExample(example.build());
//    }
//
//    /**
//     * 根据id 集合删除数据.
//     */
//    public int deleteByRecordIdList(List<T> recordList) {
//        return deleteByIdList(recordList.stream().map(BaseDbPo::getId).collect(Collectors.toList()));
//    }
//
//    /**
//     * 根据id 集合删除数据.
//     */
//    public int deleteByIdList(List<Long> idList) {
//
//        if (CollUtil.isEmpty(idList) || CollUtil.hasNull(idList)) {
//            return 0;
//        }
//
//        Example example = this.example().where(Sqls.custom().andIn("id", idList)).build();
//
//        T record = instance();
//        setModifierAndTimeIfNeeded(record);
//        //先更新操作人
//        baseMapper.updateByExampleSelective(record, example);
//        //再删除
//        return baseMapper.deleteByExample(example);
//    }
//
//    /**
//     * 批量插入数据.
//     */
//    public int insertList(List<T> list) {
//
//        if (CollUtil.isEmpty(list) || CollUtil.hasNull(list)) {
//            return 0;
//        }
//
//        //循环插入,不使用 insertList,因为insertList 默认会带上所有的字段,不会触发数据库的默认值设置.
//        return list.stream().mapToInt(this::insertSelective).sum();
//
//
////        list.forEach(e -> {
////            setCreatorAndTimeIfNeeded(e);
////            setWriteBizCode(e);
////        });
////        return mapper.insertList(list);
//    }
//
//    /**
//     * 强校验id不为null.
//     */
//    protected void assertPrimaryKeyNotNull(Object obj) {
//        if (obj == null) {
//            throw BaseException.of("数据id不存在,不允许操作.").code("0000000001");
//        }
//
//        if (obj instanceof BaseDbPo) {
//            assertPrimaryKeyNotNull(((BaseDbPo) obj).getId());
//        }
//
//    }
//
//    /**
//     * 获取当前service所对应的实体类.
//     */
//    public T instance() {
//        try {
//            return classByT().getConstructor().newInstance();
//        } catch (Exception e) {
//            log.error(e);
//        }
//        throw BaseException.of("Po 类未正确继承,请检查.").code("0000000015");
//    }
//
//    /**
//     * 当前service 实际的泛型类型
//     */
//    @SuppressWarnings("unchecked")
//    public Class<T> classByT() {
//        return (Class<T>) ClassUtil.getTypeArgument(this.getClass());
//    }
//
//    /**
//     * 设置默认创建时间和创建者.
//     */
//    private void setCreatorAndTimeIfNeeded(T record) {
//        if (ReflectUtil.hasField(record.getClass(), "creator")) {
//            ReflectUtil.setFieldValue(record, "creator", "当前用户名称" );  //RequestHolderUtil.currUser().getUsername()
//        }
//
//        if (ReflectUtil.hasField(record.getClass(), "createTime")) {
//            ReflectUtil.setFieldValue(record, "createTime", new Date());
//        }
//
//        setModifierAndTimeIfNeeded(record);
//    }
//
//    /**
//     * 手写 sql 进行查询.
//     */
//    public List<T> listBySql(String sql) {
////        sql = EscapeUtil.escapeAll(sql);
//        return baseMapper.listBySql(sql);
//    }
//
//    public List<T> selectAggregateByExample(Example example, AggregateCondition aggregateCondition) {
//        List<T> ts = baseMapper.selectAggregationByExample(example, aggregateCondition);
//        CollUtil.removeNull(ts);
//        return ts;
//    }
//
//    /**
//     * 设置默认更新时间和更新者.
//     */
//    private void setModifierAndTimeIfNeeded(T record) {
//        if (ReflectUtil.hasField(record.getClass(), "modifier")) {
//            ReflectUtil.setFieldValue(record, "modifier", "当前用户名称" );  //RequestHolderUtil.currUser().getUsername()
//        }
//
//        if (ReflectUtil.hasField(record.getClass(), "updateTime")) {
//            ReflectUtil.setFieldValue(record, "updateTime", new Date());
//        }
//    }
//
//    //todo 需要处理 record 里自带 bizCode 字段的场景
//    protected void setWriteBizCode(T record) {
//        String str = BizCodeConfig.bizCodeForQuery();
//        str = bizCodeConvert(str, BizCodeLevel.Scope.write);
//        record.setBizCode(str);
//    }
//
//    /**
//     * 根据规则以及Level的约束生成最终的 bizCode.
//     */
//    private String bizCodeConvert(String bizCodeUnderLineStr, BizCodeLevel.Scope scope) {
//
//        //当前实体的注解,标记是否满足特殊场景,如 spu 集团写.继承读.
//        BizCodeLevel annotation = AnnotationUtil.getAnnotation(classByT(), BizCodeLevel.class);
//
//        //对应的 bizCodeUnderLineStr
//        return BizCodeLevel.Level.bizCodeByLevelAndBizCodeUnderLineStr(annotation, scope, bizCodeUnderLineStr);
//    }
//
//    private void handleSqlException(Exception e) {
//        throw BaseException.of("执行sql出现异常:{}", e.getMessage(), e).code("0000000013");
//    }
//
//    /**
//     * 根据 id 判断 enable 字段值是否为 true
//     *
//     * @param key 主键 id
//     * @return 是否有效
//     */
//    public boolean isEnable(Long key) {
//        T t = selectByPrimaryKeyAndEnable(key, null);
//
//        if (t == null) {
//            throw BaseException.of("数据不存在.id:{}", key).code("0000000002");
//        }
//
//        if (ReflectUtil.hasField(t.getClass(), "enable")) {
//            Object enable = ReflectUtil.getFieldValue(t, "enable");
//            return BooleanUtil.isTrue(Convert.toBool(enable, false));
//        }
//
//        throw BaseException.of("当前数据不存在有效无效字段,请确认.id:{}", key).code("0000000003");
//    }
//
//    public void enable(Long id, boolean enable) {
//        T t = selectByPrimaryKeyAndEnable(id, null);
//
//        if (t == null) {
//            throw BaseException.of("数据不存在.id:{}", id).code("0000000001");
//        }
//
//        if (ReflectUtil.hasField(t.getClass(), "enable")) {
//            ReflectUtil.setFieldValue(t, "enable", enable);
//            updateByPrimaryKeySelective(t);
//        } else {
//            throw BaseException.of("当前数据不存在有效无效字段,请确认.id:{}", id).code("0000000003");
//        }
//    }
//
//    /**
//     * 构建 like 查询的参数
//     */
//    public String buildLikeParam(Object param) {
//        if (StrUtil.isBlank(Convert.toStr(param))) {
//            throw BaseException.of("构建 like 查询参数失败,不是有效的参数.").code("0000000005");
//        }
//
//        String str = Convert.toStr(param);
//        str = StrUtil.replaceChars(str, PERCENT, BACKSLASH + PERCENT);
//        str = StrUtil.replaceChars(str, UNDER_LINE, BACKSLASH + UNDER_LINE);
//
//        return StrUtil.format("{}{}{}", PERCENT, str, PERCENT);
//    }
//
//    public int selectCountByExample(Example example) {
//        return baseMapper.selectCountByExample(example);
//    }
//
//}
